﻿using NPOI.HSSF.UserModel;
using NPOI.OpenXml4Net.OPC;
using NPOI.SS.Formula.Functions;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Basic.Base.UtilityTools
{
    public class CommonTool
    {
        /// <summary>
        /// 根据以逗号分隔的字符串转换为集合
        /// </summary>
        /// <param name="strArr"></param>
        /// <returns></returns>
        public static List<int> GetStrList(string strArr)
        {
            if (string.IsNullOrWhiteSpace(strArr))
                return new List<int>();
            else
                return strArr.Split(',').Select(x => int.Parse(x)).ToList();
        }

        /// <summary>
        /// MD5加密。32位小写
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string MD5Encrypt(string str)
        {
            if (string.IsNullOrWhiteSpace(str))
                return string.Empty;

            //MD5 md5 = MD5.Create();
            //byte[] data = Encoding.Default.GetBytes(str);
            //byte[] md5data = md5.ComputeHash(data);
            //md5.Clear();
            //var md5str = "";
            //for (int i = 0; i < md5data.Length; i++)
            //{
            //    md5str += md5data[i].ToString("x").PadLeft(2, '0');
            //}
            //return md5str;

            using (MD5 md5 = MD5.Create())
            {
                byte[] msgBuffer = Encoding.UTF8.GetBytes(str);

                byte[] md5Buffer = md5.ComputeHash(msgBuffer);
                md5.Clear();
                StringBuilder sbMd5 = new StringBuilder();
                for (int i = 0; i < md5Buffer.Length; i++)
                {
                    sbMd5.Append(md5Buffer[i].ToString("x2")); //小写
                }
                return sbMd5.ToString();
            }
        }


        #region  list对象集合转DataTable

        public static DataTable ToDataTable<T>(List<T> items)
        {
            var tb = new DataTable(typeof(T).Name);

            PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo prop in props)
            {
                Type t = GetCoreType(prop.PropertyType);
                tb.Columns.Add(prop.Name, t);
            }

            foreach (T item in items)
            {
                var values = new object[props.Length];

                for (int i = 0; i < props.Length; i++)
                {
                    values[i] = props[i].GetValue(item, null);
                }

                tb.Rows.Add(values);
            }

            return tb;
        }

        public static bool IsNullable(Type t)
        {
            return !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
        }

        public static Type GetCoreType(Type t)
        {
            if (t != null && IsNullable(t))
            {
                if (!t.IsValueType)
                {
                    return t;
                }
                else
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            else
            {
                return t;
            }
        }

        #endregion


        /// <summary>
        /// 读取excel模板标题
        /// </summary>
        /// <param name="stream">excel stream</param>
        /// <returns></returns>
        public static List<string> GetExcelTemplateTitles(Stream stream, string fileExtension)
        {
            List<string> list = new List<string>();

            IWorkbook workBook = null;
            //IWorkbook workBook = WorkbookFactory.Create(stream);
            if (".xls".Equals(fileExtension))
            {
                workBook = new HSSFWorkbook(stream);
            }
            else if (".xlsx".Equals(fileExtension))
            {
                workBook = new XSSFWorkbook(OPCPackage.Open(stream));
            }
            else
            {
                return list;
            }


            ISheet sheet = workBook.GetSheetAt(0);
            //获取表头 FirstRowNum 第一行索引 0
            IRow header = sheet.GetRow(sheet.FirstRowNum); //获取第一行
            if (header == null)
                return list;

            var startRow = sheet.FirstRowNum + 1;
            for (int i = header.FirstCellNum; i < header.LastCellNum; i++)
            {
                ICell cell = header.GetCell(i); //标题
                if (cell != null)
                    list.Add(cell.ToString());
                else
                    list.Add("");
            }

            return list;
        }

        /// <summary>
        /// excel转DataTable
        /// </summary>
        /// <param name="workBook"></param>
        /// <returns></returns>
        public static DataTable ToExcelDataTable(IWorkbook workBook)
        {
            DataTable dataTable = new DataTable();

            if (workBook == null)
                return dataTable;

            ISheet sheet = workBook.GetSheetAt(0);
            //获取表头 FirstRowNum 第一行索引 0
            IRow header = sheet.GetRow(sheet.FirstRowNum); //获取第一行
            if (header == null)
                return dataTable;

            int startRow = 0; //数据的第一行索引
            startRow = sheet.FirstRowNum + 1;
            for (int i = header.FirstCellNum; i < header.LastCellNum; i++)
            {
                ICell cell = header.GetCell(i); //标题
                if (cell != null)
                {
                    string cellValue = cell.ToString();
                    if (cellValue != null)
                    {
                        DataColumn col = new DataColumn(cellValue);
                        dataTable.Columns.Add(col);
                    }
                    //else
                    //{
                    //    DataColumn col = new DataColumn();
                    //    dataTable.Columns.Add(col);
                    //}
                }
            }

            // 数据LastRowNum 最后一行的索引
            for (int i = startRow; i <= sheet.LastRowNum; i++)
            {
                IRow row = sheet.GetRow(i); //获取第i行
                if (row == null)
                {
                    continue;
                }
                DataRow dr = dataTable.NewRow();
                //遍历每行的单元格
                for (int j = row.FirstCellNum; j < row.LastCellNum; j++)
                {
                    if (row.GetCell(j) != null)
                        dr[j] = row.GetCell(j).ToString();
                }

                if (!IsColumnEmpty(dr)) //空行
                    dataTable.Rows.Add(dr);
            }

            return dataTable;
        }

        /// <summary>
        /// excel stream转DataTable
        /// </summary>
        /// <param name="stream">excel stream</param>
        /// <returns></returns>
        public static DataTable ExcelStreamToDatelable(Stream stream, string fileExtension)
        {
            //IWorkbook workBook = WorkbookFactory.Create(stream);

            IWorkbook workBook = null;
            if (".xls".Equals(fileExtension))
            {
                workBook = new HSSFWorkbook(stream);
            }
            else if (".xlsx".Equals(fileExtension))
            {
                workBook = new XSSFWorkbook(OPCPackage.Open(stream));
            }

            return ToExcelDataTable(workBook);
        }

        /// <summary>
        /// 判断当前行是否为空行
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        private static bool IsColumnEmpty(DataRow dr)
        {
            if (dr == null)
                return true;
            else
            {
                foreach (var value in dr.ItemArray)
                {
                    if (value == null)
                        continue;

                    var res = string.IsNullOrWhiteSpace(value.ToString());
                    if (!res)
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        private static string? _locaIP;
        public static string GetLocalIP()
        {
            if (_locaIP == null)
            {
                var entry = Dns.GetHostEntry(Dns.GetHostName());
                var list = entry?.AddressList;
                _locaIP = list?.Where(s => s.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault()?.ToString();
            }
            return _locaIP;
        }

    }
}
